package com.joonhat.MonkeyFlash;

import net.rim.device.api.system.ApplicationManager;
import net.rim.device.api.system.Backlight;
import net.rim.device.api.system.Characters;
import net.rim.device.api.system.EventInjector.KeyEvent;
import net.rim.device.api.ui.UiApplication;

public class DanceFlash {

	private static FlashKeyEvent keyEvent = FlashKeyEvent.getIns();
	private static ScreenCtrl screenCtrl = ScreenCtrl.getIns();
	private static Option option = Option.getIns();
	
	private static Thread threadOflimitFlash;
	private static ApplicationManager appManager = ApplicationManager
			.getApplicationManager();
	private static boolean onOrOffFlash;

	private DanceFlash() {}
	
	public static void toggleSimpleFlash() {
		runVideoRecorder();
		popMyScreen();
		postSpaceKey();
		pushMyScreen();
		setOnOrOffFlash();
	}
	
	public static void toggleDanceFlash(){
		if (threadOflimitFlash == null || threadOflimitFlash.isAlive() == false){
			runVideoRecorder();
			screenCtrl.popMyScreen(true);
			startDanceThread();
		} else {
			interruptThread();
		}
	}

	public static boolean isVRForeground(){
		return Constant.APP_MANAGER.getForegroundProcessId() ==
				Constant.APP_MANAGER.getProcessId(Constant.VR_DESCRIPTOR);
	}
	
	public static void interruptThread() {
		for (int i = 0; i < 3; i++) {
			try {
				if (threadOflimitFlash == null
						|| threadOflimitFlash.isAlive() == false) return;
				new Thread() {
					public void run() {
						threadOflimitFlash.interrupt();
					};
				}.start();
				Thread.sleep(50);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
	
	public static Thread getThreadIns() {
		if (threadOflimitFlash == null){
			threadOflimitFlash = new Thread();
		}
		return threadOflimitFlash;
	}

	public static void runVideoRecorder() {
		try {
			if (alreadyVideoRecoder()) return;
			appManager.runApplication(Constant.VR_DESCRIPTOR, true);
			waitExecute();
		} catch (Exception e) {
			e.printStackTrace();
		}

	}
	
	public static void closeVideoRecorder() {
		synchronized (UiApplication.getEventLock()) {
			screenCtrl.popMyScreen(true);
		}
		postEscKey();
		synchronized (UiApplication.getEventLock()) {
			screenCtrl.pushMyScreen(true);
		}
	}

	private static synchronized void startDanceThread() {
		threadOflimitFlash = new Thread(new Runnable() {
			public void run() {
				try {
					Backlight.enable(true, Integer.MAX_VALUE);
					while (true) {
						if (isVRForeground() == false) break;
						blinkFlash();
					}
				} catch (InterruptedException e) {
					e.printStackTrace();
				} finally {
					try {
						checkFlashOff();
					} catch (InterruptedException e) {
					} finally {
						synchronized (UiApplication.getEventLock()) {
							pushMyScreen();
						}
						Backlight.setTimeout(Backlight.getTimeoutDefault());
					}
				}
			}
			
		});
		threadOflimitFlash.start();
	}
	
	private static int getOntime(){
		return Integer.parseInt(option.getBlinkOnTime());
	}
	
	private static int getOfftime(){
		return Integer.parseInt(option.getBlinkOffTime());
	}
	
	private static void blinkFlash() throws InterruptedException {
		checkFlashOff();
		Thread.sleep(getOfftime());
		flashOn();
		Thread.sleep(getOntime());
		flashoff();
	}

	private static void flashoff() {
		try{
		keyEvent.postSpaceKey();
		} finally{
			onOrOffFlash = false;
		}
	}

	private static void flashOn() {
		try{
		keyEvent.postSpaceKey();
		} finally{
			onOrOffFlash = true;
		}
	}

	private static void checkFlashOff() throws InterruptedException {
		if (isOnOrOffFlash() == false) return;
		try{
		Thread.sleep(10);
		} finally {
		flashoff();
		Thread.sleep(10);
		}
	}

	private static void postSpaceKey() {
		keyEvent.postSpaceKey();
	}

	private static void postEscKey() {
		keyEvent.postEscKey();
	}

	private static void waitExecute() throws InterruptedException {
		for (int i = 0; i < 30; i++){
			Thread.sleep(100);
			if (DanceFlash.isVRForeground()) {
				Thread.sleep(150);	
				break;
			}
		}
	}
	
	private static boolean alreadyVideoRecoder() throws InterruptedException  {
		return appManager.getProcessId(Constant.VR_DESCRIPTOR) != -1
				&& DanceFlash.isVRForeground();
	}
	
	private static void popMyScreen() {
		screenCtrl.popMyScreen(true);
	}
	
	private static void pushMyScreen() {
		screenCtrl.pushMyScreen(true);
	}

	private static boolean isOnOrOffFlash() {
		return onOrOffFlash;
	}

	private static void setOnOrOffFlash() {
		if (DanceFlash.onOrOffFlash){
			DanceFlash.onOrOffFlash = false;
		} else {
			DanceFlash.onOrOffFlash = true;
		}
	}
}


class FlashKeyEvent{

	private static FlashKeyEvent keyEvent = new FlashKeyEvent();
	
	private KeyEvent spaceKey = new KeyEvent(KeyEvent.KEY_DOWN,
			Characters.SPACE, 0);
	private KeyEvent escKey = new KeyEvent(KeyEvent.KEY_DOWN,
			Characters.ESCAPE, 0);
	
	private FlashKeyEvent() {}
	
	public static FlashKeyEvent getIns(){
		return keyEvent;
	}
	
	public void postSpaceKey(){
		spaceKey.post();
		try {
			Thread.sleep(30);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	public void postEscKey(){
		escKey.post();
		try {
			Thread.sleep(50);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

